home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / redisplay-tty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-18  |  29.3 KB  |  1,085 lines

  1. /* Communication module for TTY terminals.
  2.    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
  3.  
  4. This file is part of XEmacs.
  5.  
  6. XEmacs is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by the
  8. Free Software Foundation; either version 2, or (at your option) any
  9. later version.
  10.  
  11. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with XEmacs; see the file COPYING.  If not, write to the Free
  18. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Synched up with: Divergent from FSF. */
  21.  
  22. /* This file has been Mule-ized, but needs more work before it will
  23.    compile with Mule support enabled. */
  24.  
  25. /* Written by Chuck Thompson. */
  26.  
  27. #include <config.h>
  28. #include "lisp.h"
  29.  
  30. #include "buffer.h"
  31. #include "device.h"
  32. #include "device-tty.h"
  33. #include "events.h"
  34. #include "faces.h"
  35. #include "frame.h"
  36. #include "glyphs.h"
  37. #include "redisplay.h"
  38. #include "sysdep.h"
  39. #include "window.h"
  40.  
  41. /* These headers #define all kinds of common words like "columns"...
  42.    What a bunch of losers.  If we were to include them, we'd have to
  43.    include them last to prevent them from messing up our own header
  44.    files (struct slot names, etc.).  But it turns out that there are
  45.    other conflicts as well on some systems, so screw it: we'll just
  46.    re-declare the routines we use and assume the code in this file is
  47.    invoking them correctly. */
  48. /* # include <curses.h> */
  49. /* # include <term.h> */
  50. extern int tgetent (CONST char *, CONST char *);
  51. extern int tgetflag (CONST char *);
  52. extern int tgetnum (CONST char *);
  53. extern char *tgetstr (CONST char *, char **);
  54. extern void tputs (CONST char *, int, void (*)(int));
  55. char *tparam (CONST char *string, char *outstring, int len, int arg1, int arg2,
  56.           int arg3, int arg4, int arg5, int arg6, int arg7, int arg8,
  57.           int arg9);
  58. #define OUTPUTN(d, a, n) \
  59.   do { cmputc_device = d; tputs (a, n, cmputc); } while (0)
  60. #define OUTPUT1(d, a) OUTPUTN (d, a, 1)
  61. #define OUTPUTN_IF(d, a, n) \
  62.   do { cmputc_device = d; if (a) tputs (a, n, cmputc); } while (0)
  63. #define OUTPUT1_IF(d, a) OUTPUTN_IF (d, a, 1)
  64.  
  65. static void tty_output_string (struct window *w, struct display_line *dl,
  66.                    emchar_dynarr *buf, int xpos, face_index findex,
  67.                    int cursor);
  68. static void tty_turn_on_face (struct window *w, face_index findex);
  69. static void tty_turn_off_face (struct window *w, face_index findex);
  70.  
  71. /*****************************************************************************
  72.  tty_font_metric_info
  73.  
  74.  tty's don't have fonts (that we use at least), so this actually
  75.  ignores the font argument and just returns some constants.
  76.  ****************************************************************************/
  77. static void
  78. tty_font_metric_info (struct device *d, Lisp_Object font,
  79.               struct font_metric_info *fm)
  80. {
  81.   fm->width = 1;
  82.   fm->height = 1;
  83.   fm->ascent = 1;
  84.   fm->descent = 0;
  85.   fm->proportional = 0;
  86. }
  87.  
  88. /*****************************************************************************
  89.  tty_text_width
  90.  
  91.  tty's don't have fonts (that we use at least), so everything is
  92.  considered to be fixed width.  In other words, we just return len.
  93.  ****************************************************************************/
  94. static int
  95. tty_text_width (struct window *w, Lisp_Object font, CONST Emchar *s,
  96.         Charcount len)
  97. {
  98. #ifdef MULE
  99.   /* !!####
  100.  
  101.      This might get more complicated.  Some extended characters
  102.      have a width of 2. */
  103. #endif
  104.   return len;
  105. }
  106.  
  107. /*****************************************************************************
  108.  tty_divider_width
  109.  
  110.  Return the width of the vertical divider.  This is a function because
  111.  divider_width is a device method.
  112.  ****************************************************************************/
  113. static int
  114. tty_divider_width (void)
  115. {
  116.   return 1;
  117. }
  118.  
  119. /*****************************************************************************
  120.  tty_divider_height
  121.  
  122.  Return the width of the horizontal divider.  This is a function
  123.  because divider_height is a device method.
  124.  ****************************************************************************/
  125. static int
  126. tty_divider_height (void)
  127. {
  128.   return 1;
  129. }
  130.  
  131. /*****************************************************************************
  132.  tty_eol_cursor_width
  133.  
  134.  Return the width of the end-of-line cursor.  This is a function
  135.  because eol_cursor_width is a device method.
  136.  ****************************************************************************/
  137. static int
  138. tty_eol_cursor_width (void)
  139. {
  140.   return 1;
  141. }
  142.  
  143. /*****************************************************************************
  144.  tty_output_begin
  145.  
  146.  Perform any necessary initialization prior to an update.
  147.  ****************************************************************************/
  148. #ifdef DEBUG_XEMACS
  149. void tty_output_begin (struct device *d);
  150. void
  151. #else
  152. static void
  153. #endif
  154. tty_output_begin (struct device *d)
  155. {
  156.   /* Termcap requires this to be a global variable so we have to
  157.      always set it for whatever tty device we are actually currently
  158.      working with. */
  159.   ospeed = DEVICE_TTY_DATA (d)->ospeed;
  160. }
  161.  
  162. /*****************************************************************************
  163.  tty_output_end
  164.  
  165.  Perform any necessary flushing of queues when an update has completed.
  166.  ****************************************************************************/
  167. #ifdef DEBUG_XEMACS
  168. void tty_output_end (struct device *d);
  169. void
  170. #else
  171. static void
  172. #endif
  173. tty_output_end (struct device *d)
  174. {
  175.   fflush (DEVICE_TTY_DATA (d)->outfd);
  176. }
  177.  
  178. /*****************************************************************************
  179.  tty_output_display_block
  180.  
  181.  Given a display line, a block number for that start line, output all
  182.  runes between start and end in the specified display block.
  183.  ****************************************************************************/
  184. static void
  185. tty_output_display_block (struct window *w, struct display_line *dl, int block,
  186.               int start, int end, int start_pixpos,
  187.               int cursor_start, int cursor_width,
  188.               int cursor_height)
  189. {
  190.   struct frame *f = XFRAME (w->frame);
  191.   emchar_dynarr *buf = Dynarr_new (Emchar);
  192.  
  193.   struct display_block *db = Dynarr_atp (dl->display_blocks, block);
  194.   rune_dynarr *rba = db->runes;
  195.   struct rune *rb;
  196.  
  197.   int elt = start;
  198.   face_index findex;
  199.   int xpos;
  200.  
  201.   rb = Dynarr_atp (rba, elt);
  202.  
  203.   if (!rb)
  204.     {
  205.       /* Nothing to do so don't do anything. */
  206.       return;
  207.     }
  208.   else
  209.     {
  210.       findex = rb->findex;
  211.       xpos = rb->xpos;
  212.     }
  213.  
  214.   if (end < 0)
  215.     end = Dynarr_length (rba);
  216.  
  217.   Dynarr_reset (buf);
  218.  
  219.   while (elt < end && Dynarr_atp (rba, elt)->xpos < start_pixpos)
  220.     {
  221.       elt++;
  222.       findex = Dynarr_atp (rba, elt)->findex;
  223.       xpos = Dynarr_atp (rba, elt)->xpos;
  224.     }
  225.  
  226.   while (elt < end)
  227.     {
  228.       rb = Dynarr_atp (rba, elt);
  229.  
  230.       if (rb->findex == findex && rb->type == CHAR && rb->object.ch != '\n'
  231.       && rb->cursor_type != CURSOR_ON)
  232.     {
  233.       Dynarr_add (buf, rb->object.ch);
  234.       elt++;
  235.     }
  236.       else
  237.     {
  238.       if (Dynarr_length (buf))
  239.         {
  240.           tty_output_string (w, dl, buf, xpos, findex, 0);
  241.           xpos = rb->xpos;
  242.         }
  243.       Dynarr_reset (buf);
  244.  
  245.       if (rb->type == CHAR)
  246.         {
  247.           findex = rb->findex;
  248.           xpos = rb->xpos;
  249.  
  250.           if (rb->object.ch == '\n')
  251.         {
  252.           /* Clear in case a cursor was formerly here. */
  253.  
  254.           Dynarr_add (buf, ' ');
  255.           tty_output_string (w, dl, buf, rb->xpos, DEFAULT_INDEX, 0);
  256.           Dynarr_reset (buf);
  257.  
  258.           cmgoto (f, dl->ypos - 1, rb->xpos);
  259.  
  260.           elt++;
  261.         }
  262.           else if (rb->cursor_type == CURSOR_ON)
  263.         {
  264.           /* There is not a distinct eol cursor on tty's. */
  265.  
  266.           Dynarr_add (buf, rb->object.ch);
  267.           tty_output_string (w, dl, buf, xpos, findex, 0);
  268.           Dynarr_reset (buf);
  269.  
  270.           cmgoto (f, dl->ypos - 1, xpos);
  271.  
  272.           xpos += rb->width;
  273.           elt++;
  274.         }
  275.         }
  276.       /* #### HLINE is actualy a little more complicated than this
  277.              but at the moment it is only used to draw a turned off
  278.              modeline and this will suffice for that. */
  279.       else if (rb->type == BLANK || rb->type == HLINE)
  280.         {
  281.           Emchar ch_to_add;
  282.           int size = rb->width;
  283.  
  284.           if (rb->type == BLANK)
  285.         ch_to_add = ' ';
  286.           else
  287.         ch_to_add = '-';
  288.  
  289.           while (size--)
  290.         Dynarr_add (buf, ch_to_add);
  291.           tty_output_string (w, dl, buf, rb->xpos, findex, 0);
  292.  
  293.           if (xpos >= cursor_start
  294.           && cursor_start < xpos + Dynarr_length (buf))
  295.         {
  296.           cmgoto (f, dl->ypos - 1, cursor_start);
  297.         }
  298.  
  299.           Dynarr_reset (buf);
  300.  
  301.           elt++;
  302.           if (elt < end)
  303.         {
  304.           rb = Dynarr_atp (rba, elt);
  305.  
  306.           findex = rb->findex;
  307.           xpos = rb->xpos;
  308.         }
  309.         }
  310.       else if (rb->type == DGLYPH)
  311.         {
  312.           Lisp_Object window;
  313.           Lisp_Object instance;
  314.  
  315.           XSETWINDOW (window, w);
  316.           instance = glyph_image_instance (rb->object.dglyph.glyph,
  317.                            window, 1);
  318.  
  319.           switch (XIMAGE_INSTANCE_TYPE (instance))
  320.         {
  321.         case IMAGE_TEXT:
  322.           {
  323.             /* #### This is way losing.  See the comment in
  324.                add_glyph_rune(). */
  325. #ifdef MULE
  326.             /* lose; */
  327.             /* !!#### Chuck, you need to lower this stuff
  328.                to the device-independent level. */
  329.             Dynarr_add (buf, 'l');
  330.             Dynarr_add (buf, 'o');
  331.             Dynarr_add (buf, 's');
  332.             Dynarr_add (buf, 'e');
  333. #else
  334.             Bytecount lossage;
  335.             Lisp_Object string =
  336.               XIMAGE_INSTANCE_TEXT_STRING (instance);
  337.             
  338.             for (lossage = 0;
  339.              lossage < string_length (XSTRING (string));
  340.              lossage++)
  341.               {
  342.             if (lossage >= rb->object.dglyph.xoffset)
  343.               Dynarr_add (buf,
  344.                       (Emchar) string_byte (XSTRING (string),
  345.                                 lossage));
  346.               }
  347.  
  348.             tty_output_string (w, dl, buf, xpos, findex, 0);
  349.             
  350.             if (xpos >= cursor_start
  351.             && cursor_start < xpos + Dynarr_length (buf))
  352.               {
  353.             cmgoto (f, dl->ypos - 1, cursor_start);
  354.               }
  355.             
  356.             Dynarr_reset (buf);
  357. #endif
  358.           }
  359.           break;
  360.  
  361.         case IMAGE_MONO_PIXMAP:
  362.         case IMAGE_COLOR_PIXMAP:
  363.         case IMAGE_SUBWINDOW:
  364.           /* just do nothing here */
  365.           break;
  366.  
  367.         case IMAGE_CURSOR:
  368.           abort ();
  369.  
  370.         case IMAGE_NOTHING:
  371.           /* nothing is as nothing does */
  372.           break;
  373.  
  374.         default:
  375.           abort ();
  376.         }
  377.  
  378.           xpos += rb->width;
  379.           elt++;
  380.         }
  381.       else
  382.         abort ();
  383.     }
  384.     }
  385.  
  386.   if (Dynarr_length (buf))
  387.     tty_output_string (w, dl, buf, xpos, findex, 0);
  388.   Dynarr_free (buf);
  389.  
  390. }
  391.  
  392. /*****************************************************************************
  393.  tty_output_vertical_divider
  394.  
  395.  Draw a vertical divider down the left side of the given window.
  396.  ****************************************************************************/
  397. static void
  398. tty_output_vertical_divider (struct window *w, int clear)
  399. {
  400.   struct frame *f = XFRAME (w->frame);
  401.   struct device *d = XDEVICE (f->device);
  402.   int line;
  403.   int y1 = WINDOW_TEXT_TOP (w);
  404.   int y2 = WINDOW_TEXT_BOTTOM (w);
  405.  
  406.   for (line = y1; line < y2; line++)
  407.     {
  408.       cmgoto (f, line, WINDOW_TEXT_LEFT (w) - 1);
  409.       fputc ('|', DEVICE_TTY_DATA (d)->outfd);
  410.       TTY_INC_CURSOR_X (d, 1);
  411.     }
  412.  
  413.   /* Draw the divider in the modeline. */
  414.   cmgoto (f, y2, WINDOW_TEXT_LEFT (w) - 1);
  415.   tty_turn_on_face (w, MODELINE_INDEX);
  416.   fputc ('|', DEVICE_TTY_DATA (d)->outfd);
  417.   TTY_INC_CURSOR_X (d, 1);
  418.   tty_turn_off_face (w, MODELINE_INDEX);
  419. }
  420.  
  421. /*****************************************************************************
  422.  tty_clear_to_window_end
  423.  
  424.  Clear the area between ypos1 and ypos2.  Each margin area and the
  425.  text area is handled separately since they may each have their own
  426.  background color.
  427.  ****************************************************************************/
  428. static void
  429. tty_clear_to_window_end (struct window *w, int ypos1, int ypos2)
  430. {
  431.   struct frame *f = XFRAME (w->frame);
  432.   struct device *d = XDEVICE (f->device);
  433.   int x, width;
  434.  
  435.   x = WINDOW_TEXT_LEFT (w);
  436.   width = WINDOW_TEXT_WIDTH (w);
  437.  
  438.   if (window_is_rightmost (w))
  439.     {
  440.       /* #### Optimize to use clr_to_eol function of tty if available, if
  441.      the window is the entire width of the frame. */
  442.       /* #### Is this actually an optimization? */
  443.       int line;
  444.       for (line = ypos1; line < ypos2; line++)
  445.     {
  446.       cmgoto (XFRAME (w->frame), line, x);
  447.       OUTPUT1 (d, TTY_SE (d).clr_to_eol);
  448.     }
  449.     }
  450.   else
  451.     {
  452.       Lisp_Object window;
  453.  
  454.       XSETWINDOW (window, w);
  455.       tty_clear_region (window, DEFAULT_INDEX, x, ypos1, width, ypos2 - ypos1);
  456.     }
  457. }
  458.  
  459. /****************************************************************************
  460.  tty_clear_region
  461.  
  462.  Clear the area in the box defined by the given parameters.
  463.  ****************************************************************************/
  464. void
  465. tty_clear_region (Lisp_Object window, face_index findex, int x, int y,
  466.           int width, int height)
  467. {
  468.   struct window *w = XWINDOW (window);
  469.   struct frame *f = XFRAME (w->frame);
  470.   struct device *d = XDEVICE (f->device);
  471.   int line;
  472.  
  473.   if (!width || !height)
  474.      return;
  475.  
  476.   for (line = y; line < y + height; line++)
  477.     {
  478.       int col;
  479.  
  480.       cmgoto (f, line, x);
  481.  
  482.       if (window_is_leftmost (w)
  483.       && window_is_rightmost (w)
  484.       && TTY_SE (d).clr_to_eol)
  485.     {
  486.       OUTPUT1 (d, TTY_SE (d).clr_to_eol);
  487.     }
  488.       else
  489.     {
  490.       /* #### This should be static and adjusted as necessary. */
  491.       /* #### Of course, this is all complete and utter crap. */
  492.       bufbyte_dynarr *buf = Dynarr_new (Bufbyte);
  493.  
  494.       for (col = x; col < x + width; col++)
  495.         Dynarr_add (buf, ' ');
  496.       Dynarr_add (buf, '\0');
  497.       fputs ((char *) Dynarr_atp (buf, 0), DEVICE_TTY_DATA (d)->outfd);
  498.       TTY_INC_CURSOR_X (d, Dynarr_length (buf));
  499.       Dynarr_free (buf);
  500.     }
  501.     }
  502.  
  503.   cmgoto (f, y, x);
  504. }
  505.  
  506. /****************************************************************************
  507.  tty_clear_frame
  508.  
  509.  Clear the entire frame.
  510.  ****************************************************************************/
  511. static void
  512. tty_clear_frame (struct frame *f)
  513. {
  514.   struct device *d = XDEVICE (f->device);
  515.  
  516.   if (TTY_SE (d).clr_frame)
  517.     {
  518.       OUTPUT1 (d, TTY_SE (d).clr_frame);
  519. #ifdef NOT_SURE
  520.       FRAME_CURSOR_X (f) = 0;
  521.       FRAME_CURSOR_Y (f) = 0;
  522. #endif
  523.     }
  524.   else
  525.     {
  526. #ifdef NOT_SURE
  527.       internal_cursor_to (f, 0, 0);
  528.       clear_to_end (f);
  529. #else
  530.       /* #### Not implemented. */
  531.       fprintf (stderr, "Not yet.\n");
  532. #endif
  533.     }
  534. }
  535.  
  536. /*****************************************************************************
  537.  tty_output_string
  538.  
  539.  Given a string and a starting position, output that string in the
  540.  given face.  If cursor is true, draw a cursor around the string.
  541.  ****************************************************************************/
  542. static void
  543. tty_output_string (struct window *w, struct display_line *dl,
  544.            emchar_dynarr *buf, int xpos, face_index findex, int cursor)
  545. {
  546.   struct frame *f = XFRAME (w->frame);
  547.   struct device *d = XDEVICE (f->device);
  548.  
  549.   /* First position the cursor. */
  550.   cmgoto (f, dl->ypos - 1, xpos);
  551.  
  552.   /* Enable any face properties. */
  553.   tty_turn_on_face (w, findex);
  554.  
  555.   /* Output the string. */
  556. #ifdef MULE
  557.   {
  558.     int i;
  559.     Emchar *s = Dynarr_atp (buf, 0);
  560.     int len = Dynarr_length (buf);
  561.     char *one_byte_string = (char *) alloca (len + 1);
  562.     for (i = 0; i < len; i++)
  563.       {
  564.     if (s[i] < 0x80)
  565.       one_byte_string[i] = (char) s[i];
  566.     else
  567.       one_byte_string[i] = 'X';
  568.       }
  569.     one_byte_string[len] = '\0';
  570.     /* #### Ben sez: need a level of abstraction here to handle
  571.        the termscript and such.
  572.  
  573.        #### Ben also sez: don't some terminals need nulls outputted
  574.        for proper timing? */
  575.     fputs (one_byte_string, DEVICE_TTY_DATA (d)->outfd);
  576.     TTY_INC_CURSOR_X (d, len);
  577.   }
  578.   /* !!#### presumably there are some escape sequences blah blah that can
  579.      be issued to support kterms and such.  Need to figure this out.
  580.      I think actually that kterms support both JIS and EUC encoding
  581.      (they can coexist at the same time because EUC uses entirely
  582.      characters with the high-bit set and JIS uses entirely seven-bit
  583.      characters). */
  584. #else
  585.   {
  586.     int i;
  587.     Emchar *s = Dynarr_atp (buf, 0);
  588.     int len = Dynarr_length (buf);
  589.     char *one_byte_string = (char *) alloca (len + 1);
  590.     for (i = 0; i < len; i++)
  591.       {
  592.     /* #### perhaps should use DASSERT? */
  593.     assert (s[i] < 0x100);
  594.     one_byte_string[i] = (char) s[i];
  595.       }
  596.     one_byte_string[len] = '\0';
  597.     /* #### Ben sez: need a level of abstraction here to handle
  598.        the termscript and such.
  599.  
  600.        #### Ben also sez: don't some terminals need nulls outputted
  601.        for proper timing? */
  602.     fputs (one_byte_string, DEVICE_TTY_DATA (d)->outfd);
  603.     TTY_INC_CURSOR_X (d, len);
  604.   }
  605. #endif
  606.  
  607.   /* Turn the face properties back off. */
  608.   tty_turn_off_face (w, findex);
  609. }
  610.  
  611. /*****************************************************************************
  612.  tty_turn_on_face
  613.  
  614.  Turn on all set properties of the given face.
  615.  ****************************************************************************/
  616. static void
  617. tty_turn_on_face (struct window *w, face_index findex)
  618. {
  619.   struct frame *f = XFRAME (w->frame);
  620.   struct device *d = XDEVICE (f->device);
  621.  
  622.   /* #### still need to handle color */
  623.  
  624.   if (FACE_CACHE_ELEMENT_HIGHLIGHT_P (w, findex))
  625.     {
  626.       OUTPUT1_IF (d, TTY_SD (d).turn_on_bold);
  627.     }
  628.  
  629.   if (FACE_CACHE_ELEMENT_REVERSE_P (w, findex))
  630.     {
  631.       /* #### punt for now if standout mode is glitchy */
  632.       if (!TTY_FLAGS (d).standout_width)
  633.     {
  634.       OUTPUT1_IF (d, TTY_SD (d).begin_standout);
  635.     }
  636.     }
  637.  
  638.   if (FACE_CACHE_ELEMENT_BLINKING_P (w, findex))
  639.     {
  640.       OUTPUT1_IF (d, TTY_SD (d).turn_on_blinking);
  641.     }
  642.  
  643.   if (FACE_CACHE_ELEMENT_DIM_P (w, findex))
  644.     {
  645.       OUTPUT1_IF (d, TTY_SD (d).turn_on_dim);
  646.     }
  647.  
  648.   if (FACE_CACHE_ELEMENT_UNDERLINE_P (w, findex))
  649.     {
  650.       /* #### punt for now if underline mode is glitchy */
  651.       if (!TTY_FLAGS (d).underline_width)
  652.     {
  653.       OUTPUT1_IF (d, TTY_SD (d).begin_underline);
  654.     }
  655.     }
  656. }
  657.  
  658. /*****************************************************************************
  659.  tty_turn_off_face
  660.  
  661.  Turn off all set properties of the given face (revert to default
  662.  face).  We assume that tty_turn_on_face has been called for the given
  663.  face so that it's properties are actually active.
  664.  ****************************************************************************/
  665. static void
  666. tty_turn_off_face (struct window *w, face_index findex)
  667. {
  668.   struct frame *f = XFRAME (w->frame);
  669.   struct device *d = XDEVICE (f->device);
  670.  
  671.   if (FACE_CACHE_ELEMENT_UNDERLINE_P (w, findex))
  672.     {
  673.       /* #### punt for now if underline mode is glitchy */
  674.       if (!TTY_FLAGS (d).underline_width)
  675.     {
  676.       OUTPUT1_IF (d, TTY_SD (d).end_underline);
  677.     }
  678.     }
  679.  
  680.   if (FACE_CACHE_ELEMENT_HIGHLIGHT_P (w, findex) ||
  681.       FACE_CACHE_ELEMENT_BLINKING_P (w, findex) ||
  682.       FACE_CACHE_ELEMENT_DIM_P (w, findex))
  683.     {
  684.       OUTPUT1_IF (d, TTY_SD (d).turn_off_attributes);
  685.     }
  686.  
  687.   if (FACE_CACHE_ELEMENT_REVERSE_P (w, findex))
  688.     {
  689.       /* #### punt for now if standout mode is glitchy */
  690.       if (!TTY_FLAGS (d).standout_width)
  691.     {
  692.       OUTPUT1_IF (d, TTY_SD (d).end_standout);
  693.     }
  694.     }
  695. }
  696.  
  697. /*****************************************************************************
  698.  set_tty_modes
  699.  
  700.  Sets up various parameters on tty modes.
  701.  ****************************************************************************/
  702. void
  703. set_tty_modes (struct device *d)
  704. {
  705.   if (!DEVICE_IS_TTY (d))
  706.     return;
  707.  
  708.   OUTPUT1_IF (d, TTY_SD (d).init_motion);
  709.   OUTPUT1_IF (d, TTY_SD (d).cursor_visible);
  710.   OUTPUT1_IF (d, TTY_SD (d).keypad_on);
  711. }
  712.  
  713. /*****************************************************************************
  714.  reset_tty_modes
  715.  
  716.  Restore default state of tty.
  717.  ****************************************************************************/
  718. void
  719. reset_tty_modes (struct device *d)
  720. {
  721.   if (!DEVICE_IS_TTY (d))
  722.     return;
  723.  
  724.   OUTPUT1_IF (d, TTY_SD (d).keypad_off);
  725.   OUTPUT1_IF (d, TTY_SD (d).cursor_normal);
  726.   OUTPUT1_IF (d, TTY_SD (d).end_motion);
  727. }
  728.  
  729.  
  730. /* #### Everything below here is old shit.  It should either be moved
  731.    up or removed. */
  732.  
  733.  
  734. /* FLAGS - these don't need to be device local since only one device
  735.         can be being updated at a time. */
  736. static int insert_mode_on;        /* nonzero if in insert mode */
  737. static int standout_mode_on;        /* nonzero if in standout mode */
  738. static int underline_mode_on;        /* nonzero if in underline mode */
  739. static int alternate_mode_on;        /* nonzero if in alternate char set */
  740. static int attributes_on;        /* nonzero if any attributes on */
  741.  
  742. #ifdef NOT_YET
  743. static void
  744. turn_on_insert (struct frame *f)
  745. {
  746.   struct device *d = XDEVICE (f->device);
  747.  
  748.   if (!insert_mode_on)
  749.     OUTPUT1_IF (d, TTY_SE (d).begin_ins_mode);
  750.   insert_mode_on = 1;
  751. }
  752.  
  753. static void
  754. turn_off_insert (struct frame *f)
  755. {
  756.   struct device *d = XDEVICE (f->device);
  757.  
  758.   if (insert_mode_on)
  759.     OUTPUT1 (d, TTY_SE (d).end_ins_mode);
  760.   insert_mode_on = 0;
  761. }
  762.  
  763. static void
  764. internal_cursor_to (struct frame *f, int row, int col)
  765. {
  766.   struct device *d = XDEVICE (f->device);
  767.  
  768.   if (!TTY_FLAGS (d).insert_mode_motion)
  769.     turn_off_insert (f);
  770.   if (!TTY_FLAGS (d).standout_motion)
  771.     {
  772.       turn_off_standout (f);
  773.       turn_off_underline (f);
  774.       turn_off_alternate (f);
  775.     }
  776.  
  777.   cmgoto (f, row, col);
  778. }
  779.  
  780. static void
  781. clear_to_end (struct frame *f)
  782. {
  783.   struct device *d = XDEVICE (f->device);
  784.  
  785.   /* assumes cursor is already positioned */
  786.   if (TTY_SE (d).clr_from_cursor)
  787.     {
  788.       OUTPUT1 (d, TTY_SE (d).clr_from_cursor);
  789.     }
  790.   else
  791.     {
  792.       int line = FRAME_CURSOR_Y (f);
  793.  
  794.       while (line < FRAME_HEIGHT (f))
  795.     {
  796.       internal_cursor_to (f, line, 0);
  797.       OUTPUT1 (d, TTY_SE (d).clr_to_eol);
  798.     }
  799.     }
  800. }
  801. #endif /* 0 */
  802.  
  803. #if 0
  804. /*
  805.  *  clear from last visible line on window to window end (presumably
  806.  *  the line above window's modeline
  807.  */
  808. static void
  809. tty_clear_window_end (struct window *w, int ystart, int yend)
  810. {
  811.   struct device *d = XDEVICE (XFRAME (w->frame)->device);
  812.   int line;
  813.  
  814.   for (line = ystart; line < yend; line++)
  815.     {
  816.       cmgoto (XFRAME (w->frame), line, 0);
  817.       OUTPUT1 (d, TTY_SE (d).clr_to_eol);
  818.     }
  819. }
  820.  
  821. /*
  822.  * tty_shift_region - shift a region between START and END to its new position
  823.  */
  824. static void
  825. tty_shift_region (struct window *w, struct line_header *start,
  826.           struct line_header *end)
  827. {
  828.   stderr_out ("tty_shift_region:  NOT YET IMPLEMENTED\n");
  829. }
  830. #endif /* 0 */
  831.  
  832. #ifdef OLD_REDISPLAY_SHIT
  833.  
  834. static void
  835. tty_update_begin (struct window *w)
  836. {
  837. }
  838.  
  839. static void
  840. tty_update_end (struct window *w)
  841. {
  842.   struct frame *f = XFRAME (w->frame);
  843.  
  844.   /* reset state */
  845.   turn_off_insert (f);
  846.   turn_off_standout (f);
  847.   turn_off_underline (f);
  848.   turn_off_alternate (f);
  849.   turn_off_attributes (f);
  850.  
  851.   internal_cursor_to (f, f->cursor_y, f->cursor_x);
  852.  
  853.   tty_flush (XDEVICE (f->device));
  854. }
  855.  
  856. static void
  857. tty_cursor_to (struct line_header *l, struct char_block *cb, int row, int col,
  858.            struct window_mirror *mir, struct frame *f)
  859. {
  860.   internal_cursor_to (f, l->ypos, cb->xpos);
  861. }
  862.  
  863. #endif /* OLD_REDISPLAY_SHIT */
  864.  
  865. static int
  866. tty_flash (struct device *d)
  867. {
  868.   if (TTY_SD (d).visual_bell)
  869.     {
  870.       OUTPUT1 (d, TTY_SD (d).visual_bell);
  871.       fflush (DEVICE_TTY_DATA (d)->outfd);
  872.       return 1;
  873.     }
  874.   else
  875.     return 0;
  876. }
  877.  
  878. /*
  879.  * tty_ring_bell - sound an audio beep.
  880.  */
  881. static void
  882. tty_ring_bell (struct device *d, int volume, int pitch, int duration)
  883. {
  884.   OUTPUT1 (d, TTY_SD (d).audio_bell);
  885.   fflush (DEVICE_TTY_DATA (d)->outfd);
  886. }
  887.  
  888. int
  889. init_tty_for_redisplay (struct device *d, char *terminal_type)
  890. {
  891.   int status;
  892.   char entry_buffer[2044];
  893.   /* char temp_buffer[2044]; */
  894.   char *bufptr;
  895.  
  896.   /* What we should really do is allocate just enough space for
  897.      the actual strings that are stored; but this would require
  898.      doing this after all the tgetstr()s and adjusting all the
  899.      pointers. */
  900.   DEVICE_TTY_DATA (d)->term_entry_buffer = (char *) xmalloc (2044);
  901.   bufptr = DEVICE_TTY_DATA (d)->term_entry_buffer; 
  902.  
  903.   status = tgetent (entry_buffer, terminal_type);
  904.   if (status < 0)
  905.     return TTY_UNABLE_OPEN_DATABASE;
  906.   else if (status == 0)
  907.     return TTY_TYPE_UNDEFINED;
  908.  
  909.   /*
  910.    * Establish the terminal size.
  911.    */
  912.   /* First try to get the info from the system.  If that fails, check
  913.      the termcap entry. */
  914.   get_tty_device_size (d, &DEVICE_TTY_DATA(d)->width,
  915.                &DEVICE_TTY_DATA(d)->height);
  916.  
  917.   if (DEVICE_TTY_DATA (d)->width <= 0)
  918.     DEVICE_TTY_DATA (d)->width = tgetnum ("co");
  919.   if (DEVICE_TTY_DATA (d)->height <= 0)
  920.     DEVICE_TTY_DATA (d)->height = tgetnum ("li");
  921.  
  922.   if (DEVICE_TTY_DATA (d)->width <= 0 || DEVICE_TTY_DATA (d)->height <= 0)
  923.     return TTY_SIZE_UNSPECIFIED;
  924.  
  925.   /*
  926.    * Initialize cursor motion information.
  927.    */
  928.  
  929.   /* local cursor movement */
  930.   TTY_CM (d).up = tgetstr ("up", &bufptr);
  931.   TTY_CM (d).down = tgetstr ("do", &bufptr);
  932.   TTY_CM (d).left = tgetstr ("le", &bufptr);
  933.   TTY_CM (d).right = tgetstr ("nd", &bufptr);
  934.   TTY_CM (d).home = tgetstr ("ho", &bufptr);
  935.   TTY_CM (d).low_left = tgetstr ("ll", &bufptr);
  936.   TTY_CM (d).car_return = tgetstr ("cr", &bufptr);
  937.  
  938.   /* absolute cursor motion */
  939.   TTY_CM (d).abs = tgetstr ("cm", &bufptr);
  940.   TTY_CM (d).hor_abs = tgetstr ("ch", &bufptr);
  941.   TTY_CM (d).ver_abs = tgetstr ("cv", &bufptr);
  942.  
  943.   /* Verify that the terminal is powerful enough to run Emacs */
  944.   if (!TTY_CM (d).abs)
  945.     {
  946.       if (!TTY_CM (d).up || !TTY_CM (d).down
  947.       || !TTY_CM (d).left || !TTY_CM (d).right)
  948.     return TTY_TYPE_INSUFFICIENT;
  949.     }
  950.  
  951.   /* parameterized local cursor movement */
  952.   TTY_CM (d).multi_up = tgetstr ("UP", &bufptr);
  953.   TTY_CM (d).multi_down = tgetstr ("DO", &bufptr);
  954.   TTY_CM (d).multi_left = tgetstr ("LE", &bufptr);
  955.   TTY_CM (d).multi_right = tgetstr ("RI", &bufptr);
  956.  
  957.   /* scrolling */
  958.   TTY_CM (d).scroll_forw = tgetstr ("sf", &bufptr);
  959.   TTY_CM (d).scroll_back = tgetstr ("sr", &bufptr);
  960.   TTY_CM (d).multi_scroll_forw = tgetstr ("SF", &bufptr);
  961.   TTY_CM (d).multi_scroll_back = tgetstr ("SR", &bufptr);
  962.   TTY_CM (d).set_scroll_region = tgetstr ("cs", &bufptr);
  963.  
  964.  
  965.   /*
  966.    * Initialize screen editing information.
  967.    */
  968.  
  969.   /* adding to the screen */
  970.   TTY_SE (d).ins_line = tgetstr ("al", &bufptr);
  971.   TTY_SE (d).multi_ins_line = tgetstr ("AL", &bufptr);
  972.   TTY_SE (d).repeat = tgetstr ("rp", &bufptr);
  973.   TTY_SE (d).begin_ins_mode = tgetstr ("im", &bufptr);
  974.   TTY_SE (d).end_ins_mode = tgetstr ("ei", &bufptr);
  975.   TTY_SE (d).ins_char = tgetstr ("ic", &bufptr);
  976.   TTY_SE (d).multi_ins_char = tgetstr ("IC", &bufptr);
  977.   TTY_SE (d).insert_pad = tgetstr ("ip", &bufptr);
  978.  
  979.   /* deleting from the screen */
  980.   TTY_SE (d).clr_frame = tgetstr ("cl", &bufptr);
  981.   TTY_SE (d).clr_from_cursor = tgetstr ("cd", &bufptr);
  982.   TTY_SE (d).clr_to_eol = tgetstr ("ce", &bufptr);
  983.   TTY_SE (d).del_line = tgetstr ("dl", &bufptr);
  984.   TTY_SE (d).multi_del_line = tgetstr ("DL", &bufptr);
  985.   TTY_SE (d).del_char = tgetstr ("dc", &bufptr);
  986.   TTY_SE (d).multi_del_char = tgetstr ("DC", &bufptr);
  987.   TTY_SE (d).begin_del_mode = tgetstr ("dm", &bufptr);
  988.   TTY_SE (d).end_del_mode = tgetstr ("ed", &bufptr);
  989.   TTY_SE (d).erase_at_cursor = tgetstr ("ec", &bufptr);
  990.  
  991.  
  992.   /*
  993.    * Initialize screen display information.
  994.    */
  995.   TTY_SD (d).begin_standout = tgetstr ("so", &bufptr);
  996.   TTY_SD (d).end_standout = tgetstr ("se", &bufptr);
  997.   TTY_SD (d).begin_underline = tgetstr ("us", &bufptr);
  998.   TTY_SD (d).end_underline = tgetstr ("ue", &bufptr);
  999.   TTY_SD (d).begin_alternate = tgetstr ("as", &bufptr);
  1000.   TTY_SD (d).end_alternate = tgetstr ("ae", &bufptr);
  1001.   TTY_SD (d).turn_on_reverse = tgetstr ("mr", &bufptr);
  1002.   TTY_SD (d).turn_on_blinking = tgetstr ("mb", &bufptr);
  1003.   TTY_SD (d).turn_on_bold = tgetstr ("md", &bufptr);
  1004.   TTY_SD (d).turn_on_dim = tgetstr ("mh", &bufptr);
  1005.   TTY_SD (d).turn_off_attributes = tgetstr ("me", &bufptr);
  1006.  
  1007.   TTY_SD (d).visual_bell = tgetstr ("vb", &bufptr);
  1008.   TTY_SD (d).audio_bell = tgetstr ("bl", &bufptr);
  1009.   if (!TTY_SD (d).audio_bell)
  1010.     {
  1011.       /* If audio_bell doesn't get set, then assume C-g.  This is gross and
  1012.          ugly but is what Emacs has done from time immortal. */
  1013.       TTY_SD (d).audio_bell = "\07";
  1014.     }
  1015.  
  1016.   TTY_SD (d).cursor_visible = tgetstr ("ve", &bufptr);
  1017.   TTY_SD (d).cursor_normal = tgetstr ("vs", &bufptr);
  1018.   TTY_SD (d).init_motion = tgetstr ("ti", &bufptr);
  1019.   TTY_SD (d).end_motion = tgetstr ("te", &bufptr);
  1020.   TTY_SD (d).keypad_on = tgetstr ("ks", &bufptr);
  1021.   TTY_SD (d).keypad_off = tgetstr ("ke", &bufptr);
  1022.  
  1023.  
  1024.   /*
  1025.    * Initialize additional terminal information.
  1026.    */
  1027.   TTY_FLAGS (d).must_write_spaces = tgetflag ("in");
  1028.   TTY_FLAGS (d).insert_mode_motion = tgetflag ("mi");
  1029.   TTY_FLAGS (d).standout_motion = tgetflag ("ms");
  1030.   TTY_FLAGS (d).memory_above_frame = tgetflag ("da");
  1031.   TTY_FLAGS (d).memory_below_frame = tgetflag ("db");
  1032.   TTY_FLAGS (d).meta_key = tgetflag ("km") || tgetflag ("MT");
  1033.   TTY_FLAGS (d).standout_width = tgetnum ("sg");
  1034.   TTY_FLAGS (d).underline_width = tgetnum ("ug");
  1035.  
  1036.   if (TTY_FLAGS (d).standout_width == -1)
  1037.     TTY_FLAGS (d).standout_width = 0;
  1038.   if (TTY_FLAGS (d).underline_width == -1)
  1039.     TTY_FLAGS (d).underline_width = 0;
  1040.  
  1041.   /*
  1042.    * Setup the costs tables for this tty device.
  1043.    */
  1044.   cm_cost_init (d);
  1045.  
  1046.   /*
  1047.    * Initialize local flags.
  1048.    */
  1049.   insert_mode_on = 0;
  1050.   standout_mode_on = 0;
  1051.   underline_mode_on = 0;
  1052.   alternate_mode_on = 0;
  1053.   attributes_on = 0;
  1054.  
  1055.   /* #### fix this */
  1056.   DEVICE_CLASS (d) = Qmono;
  1057.  
  1058.   return TTY_INIT_SUCCESS;
  1059. }
  1060.  
  1061.  
  1062. /************************************************************************/
  1063. /*                            initialization                            */
  1064. /************************************************************************/
  1065.  
  1066. void
  1067. device_type_create_redisplay_tty (void)
  1068. {
  1069.   /* redisplay methods */
  1070.   DEVICE_HAS_METHOD (tty, text_width);
  1071.   DEVICE_HAS_METHOD (tty, font_metric_info);
  1072.   DEVICE_HAS_METHOD (tty, output_display_block);
  1073.   DEVICE_HAS_METHOD (tty, output_vertical_divider);
  1074.   DEVICE_HAS_METHOD (tty, divider_width);
  1075.   DEVICE_HAS_METHOD (tty, divider_height);
  1076.   DEVICE_HAS_METHOD (tty, eol_cursor_width);
  1077.   DEVICE_HAS_METHOD (tty, clear_to_window_end);
  1078.   DEVICE_HAS_METHOD (tty, clear_region);
  1079.   DEVICE_HAS_METHOD (tty, clear_frame);
  1080.   DEVICE_HAS_METHOD (tty, output_begin);
  1081.   DEVICE_HAS_METHOD (tty, output_end);
  1082.   DEVICE_HAS_METHOD (tty, flash);
  1083.   DEVICE_HAS_METHOD (tty, ring_bell);
  1084. }
  1085.